
  function Router( config ){
    window.onload = Router.init.bind(this, config);
    window.onhashchange = Router.init.bind(this, config);
  }

  Router.init = function( config ){
    !location.hash.includes('#') && (location.hash = '#/');

    var hash = location.hash;
    var path = hash.match(/#([^?]+)\??/i)[1];

    document.querySelectorAll('[view]').forEach(function(div){
      div.innerHTML = config.routes.find(function(item){
        return item.path === path;
      }).page( parseURL(hash) ) || '';
    });

    document.querySelectorAll('[link]').forEach(function(a){
      var match = a.getAttribute('href') === hash;
      a.classList[match?'add':'remove']('active');
    })

  }

  function firstUpperCase( name ){
    return name.slice(0,1).toUpperCase() + name.slice(1);
  }

  function camelCase( name ){
    return name.toLowerCase().replace(/_([a-z])/g,function($,$1){
      return $1.toUpperCase();
    })
  }

  function pascalCase( name ){
    return firstUpperCase(camelCase( name ));
  }

  function parseURL( url ) {
    var params = {};
    if(!url.includes('?')) return params;
    var urls = url.split('?');
    
    var arr = urls[1].split('&') ;
    for (var i = 0, len = arr.length; i < len; i++) {
      var a = arr[i].split('=');
      params[a[0]] = a[1];
    }
    return params;
  }

  function pickName( url ){
    return url.match(/\/(\w+)\.[a-z]+$/)[1];
  }
  
  function pickCode(html, tag='script'){
    var codes = [];
    var reg = new RegExp('<'+tag+'>([\\s\\S]*?)<\\/'+tag+'>','igm');
    do {
      var code = reg.exec( html );
      code && codes.push(code[1]);
    }while( reg.lastIndex );
    return codes;
  }

  function importAsync( url ){
    return function( params ){

      var xhr = new XMLHttpRequest();
      xhr.onload = function(){
        var html = xhr.responseText;
        // var src = html.match(/<script[^>]+src="([^"]+)">/i);
        // console.log( src );

        var filename = pickName(url);

        var htmls = pickCode(html,'template').reduce(function(html, item){
          return html + item;
        },'');
  
        var scripts = pickCode(html).reduce(function(code, item){
          return code + item;
        },'');
  
        document.querySelectorAll('[view]').forEach(function(div){
          div.innerHTML = htmls;
        })
  
        //追加script
        if(!document.getElementById(filename)){
          var script = document.createElement('script');
          script.id = filename;
          script.textContent = scripts;
          document.body.append( script );
        }

        var callback = pascalCase(filename);
        typeof window[callback] === 'function' && window[callback](params);
       
      }
      xhr.open('GET', url );
      xhr.send();
    }
  }